﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ChunkManager
{
    private Dictionary<string, Chunk> Chunks;
    private RaycastHitVoxelInfo curSelectedVoxelInfo;

    public ChunkManager()
    {
        Chunks = new Dictionary<string, Chunk>();
        EventManager.LookupEvent += this.OnLookupHandler;
        EventManager.MouseButtonDownEvent += this.OnMouseButtonDownHandler;
    }
    private void AddChunk(Index index, Chunk chunk)
    {
        Chunks[index.ToString()] = chunk;
    }
    private void RemoveChunk(Index index)
    {
        Chunks.Remove(index.ToString());
    }
    public Chunk GetChunk(Index index)
    {
        try
        {
            string indexString = index.ToString();
            if (Chunks.ContainsKey(indexString))
            {
                return Chunks[indexString];
            }
            else
            {
                return null;
            }
        }
        catch (System.Exception)
        {
            Debug.LogError("Chunk Manager GetChunk " + index);
            return null;
        }
    }
    public static Index PositionToChunkIndex(Vector3 position)
    {
        try
        {
            return new Index((int)(position.x / Const.ChunkSideLength),
                            (int)(position.y / Const.ChunkSideLength),
                            (int)(position.z / Const.ChunkSideLength));
        }
        catch (System.Exception)
        {
            Debug.LogError("ChunkManager PositionToChunkIndex Get null Position");
            return new Index(0, 0, 0);
        }
    }
    public void SpawnChunks(Vector3 originPoint)
    {
        SpawnChunks(PositionToChunkIndex(originPoint));
    }
    public void SpawnChunks(int originX, int originY, int originZ)
    {
        Index indexTmp = null;
        GameObject chunk = null;
        GameObject chunkObject = BlocksTerrain.Instance.ChunkObject;
        Quaternion rotation = BlocksTerrain.Instance.transform.rotation;
        for (int y = originY - Const.VisibleHeight; y <= originY + Const.VisibleHeight; ++y)
        {
            for (int currentLoop = 0; currentLoop <= Const.VisibleDistance; ++currentLoop)
            {
                for (int x = originX - currentLoop; x <= originX + currentLoop; ++x)
                {
                    for (int z = originZ - currentLoop; z <= originZ + currentLoop; ++z)
                    {
                        if (x * x + z * z > Const.VisibleDistanceSQ)
                        {
                            continue;
                        }
                        indexTmp = new Index(x, y, z);
                        if (GetChunk(indexTmp) != null)
                        {
                            continue;
                        }
                        chunk = Object.Instantiate(chunkObject, new Vector3(x, y, z), rotation) as GameObject;
                        AddChunk(indexTmp, chunk.GetComponent<Chunk>());
                    }
                }
            }
        }
    }
    public void SpawnChunks(Index originIndex)
    {
        SpawnChunks(originIndex.x, originIndex.y, originIndex.z);
    }

    private void OnLookupHandler(RaycastHitVoxelInfo hitInfo)
    {
        curSelectedVoxelInfo = hitInfo;
        GameObject blockSelection = GameObject.Find(Const.SelectClubName);
        if (blockSelection == null)
        {
            Debug.LogWarning("OnLookupHandler not Found blockSelection");
            return;
        }
        Chunk chunk = (hitInfo != null) ? GetChunk(hitInfo.chunkIndex) : null;
        if (chunk != null)
        {
            blockSelection.transform.position = chunk.VoxelIndexToPosition(hitInfo.index);
            blockSelection.GetComponent<Renderer>().enabled = true;
            blockSelection.transform.rotation = chunk.transform.rotation;
        }
        else
        {
            blockSelection.GetComponent<Renderer>().enabled = false;
        }
    }

    private void OnMouseButtonDownHandler(int keyCode)
    {
        Chunk chunk = (curSelectedVoxelInfo != null) ? GetChunk(curSelectedVoxelInfo.chunkIndex) : null;
        if (chunk == null)
        {
            return;
        }
        // if (keyCode == 0)
        if (keyCode == 1)
        {
            chunk.SetVoxelTypeID(curSelectedVoxelInfo.index, Const.VoxelType_Air, true);
            // chunk.ReDraw();
        }
        // else if (keyCode == 1)
        else if (keyCode == 0)
        {
            Index belowIndex = new Index(curSelectedVoxelInfo.adjacentIndex.x
                        , curSelectedVoxelInfo.adjacentIndex.y - 1
                        , curSelectedVoxelInfo.adjacentIndex.z);
            if (chunk.GetVoxelTypeID(belowIndex) == Const.VoxelType_Grass)
            {
                chunk.SetVoxelTypeID(belowIndex, Const.VoxelType_Clod, true);
            }
            chunk.SetVoxelTypeID(curSelectedVoxelInfo.adjacentIndex, Const.VoxelType_Grass, true);
            // chunk.ReDraw();
        }
    }
}
